#include <log.h>
#include "mdns.h"
#include "json.h"
#include "ini.h"
#include "Net.h"
#include "ConfigApi.h"
#include <fstream>
#include "WlanService.h"

using namespace ConfigApi;

namespace Media{


#define DEV_HARDWARE_PATH "/mnt/mtd/Sys/hardwareTest.ini"
#define INI_NETWORK_PATH "/mnt/mtd/Config/netWork.ini"

Mdns *Mdns::sm_Mdns = nullptr;
mutex Mdns::sm_instanceLock;
const std::string configPathCurtain = "/mnt/mtd/Config/Config11";

//C语言调用初始化函数创建单例
extern "C" void MdnsInit(){
	Mdns::instance();
}

//单例模式调用构造方法
Mdns *Mdns::instance(){
	if(sm_Mdns == nullptr){
		lock_guard<mutex> lock(sm_instanceLock);
		sm_Mdns = new Mdns();
	}
	return sm_Mdns;
}




//构造方法中创建一个线程调用函数
Mdns::Mdns(){
	thread mdns(&Mdns::startMdns, this);
	mdns.detach();
}


bool Mdns::getCmdInfo(char *cmd, vector<string> &info){
	if(cmd == NULL || strlen(cmd) == 0){
		LOG_PrintError("cmd is empty\n");
		return false;
	}
	char buf[1024] = {0};
	FILE *fp = popen(cmd, "r");
	if(fp)
	{
		while(fgets(buf, sizeof(buf), fp))
		{	
			info.push_back(buf);
			//LOG_PrintInfo("buf --> %s\n", buf);
			memset(buf, 0, sizeof(buf));
		}
		pclose(fp);
	}else{
		LOG_PrintError("process cmd is error:%s\n", cmd);
		return false;
	}
#if 0
	for(int i = 0; i < info.size(); i++){
		LOG_PrintInfo("buf --> %s\n", info[i].c_str());
	}
#endif
	return true;
}

//真正的调用函数
void *Mdns::startMdns(){
	//调用mdns初始化函数
	bool mark = false;
	char name_prefix[32] = {0};

	#if defined(MODEL_ROOMS) 
    memcpy(name_prefix, "NearHub_rooms_", sizeof(name_prefix));
    
	#else
	memcpy(name_prefix, "NearHub_air_", sizeof(name_prefix));
	#endif

    LOG_PrintInfo("MDNS name_prefix:%s\n", name_prefix);
	
	char *devtype = "_awx_service._tcp.";
	Json::Value mdns_table;
	char snid[64] = {0};
	char ip_addr[16] = {0};
	char mac_addr[32] = {0};
	char busy[5] = {0};

	int status_get_snid = INI_KeyGetString(DEV_HARDWARE_PATH, "hardwareTest", "snid", snid);
	if(status_get_snid < 0){
		LOG_PrintError("MDNS get snid fail\n");
	}

	int ret = broadcast_init(name_prefix, devtype, snid);
	if(ret < 0){
		LOG_PrintError("MDNS broadcast_init fail\n");
	}
	//LOG_PrintInfo(" WLanConnChk() != 0:%d\n",  WLanConnChk() != 0);
	//循环持续更新
	while(1){
		//准备参数拼接成json
		//添加一个版本
		int status_get_ip = INI_KeyGetString(SYS_NETCFG_FILE, "eth0", "ip", ip_addr);
		int status_get_mac = INI_KeyGetString(INI_NETWORK_PATH, "network", "macaddr", mac_addr);
		status_get_snid = INI_KeyGetString(DEV_HARDWARE_PATH, "hardwareTest", "snid", snid);
		//获取名字
		Json::Value passTable;
		Json::Value nameTable;
		string name;
		string init;
		IConfigInterface::GetInstance()->Get("DevPasswd", passTable);
		//if(!passTable.isMember("Keys") || !passTable["Keys"].isString() || passTable["Keys"].asString().empty() || !WlanService::instance()->getWirelessStatus()){
		if(!passTable.isMember("Keys") || !passTable["Keys"].isString() || passTable["Keys"].asString().empty()){
			init = "0";
		}else{
			init = "1";
		}
		IConfigInterface::GetInstance()->Get("DevName", nameTable);
		if(nameTable.isMember("Name") && nameTable["Name"].isString()){
			name = nameTable["Name"].asString();
		}else{
			name = "";
		}
		

		if(status_get_snid < 0){
			LOG_PrintError("MDNS get snid fail\n");
		}
		if(status_get_ip < 0){
			LOG_PrintError("MDNS get ip fail\n");
		}
		if(status_get_mac < 0){
			LOG_PrintError("MDNS get mac_addr fail\n");
		}


		//如果json中不存在需要发送的值或者值一已经改变，就更新json,并且更新标志位
		if(!mdns_table.isMember("ip") || mdns_table["ip"] != ip_addr){
			mdns_table["ip"] = ip_addr;
			mark = true;
		}
		if(!mdns_table.isMember("mac") || mdns_table["mac"] != mac_addr){
			mdns_table["mac"] = mac_addr;
			mark = true;
		}
		if(!mdns_table.isMember("snid") || mdns_table["snid"] != snid){
			mdns_table["snid"] = snid;
			mark = true;
		}

		if(!mdns_table.isMember("name") || mdns_table["name"] != name){
			mdns_table["name"] = name;
			mark = true;
		}

		if(!mdns_table.isMember("init") || mdns_table["init"] != init){
			mdns_table["init"] = init;
			mark = true;
		}
		//调用函数
		if(mark){
			LOG_PrintError("MDNS json_tablee:%s\n", mdns_table.toStyledString().c_str());
			int ret = broadcast_message((char *)mdns_table.toStyledString().c_str());
			if(ret < 0){
				LOG_PrintError("MDNS broadcast_message fail\n");
			}
			mark = false;
		}
		//延时函数
		usleep(500 * 1000);
	}
}

std::vector<std::string> Mdns::stringSplit(const std::string& str, char delim) {
    std::stringstream ss(str);
    std::string item;
    std::vector<std::string> elems;
    while (std::getline(ss, item, delim)) {
        if (!item.empty()) {
            elems.push_back(item);
        }
    }
    return elems;
}


DeviceInfo Mdns::ParseDeviceMDnsData(const std::string &src_device_info) {
	DeviceInfo device_info = {};
	string val;
	vector<string> serverNames = stringSplit(src_device_info, ' ');
	for (int index = 0; index < serverNames.size(); index++) {
		val = serverNames[index];
		//LOG_PrintInfo("val: %s\n", val.c_str());
		if (val.find("ip=") != std::string::npos) {
			device_info.device_ip = val.substr(val.find("ip=") + strlen("ip="), val.size() - strlen("ip=") - 2);
		}  else if (val.find("name=") != std::string::npos) {
			device_info.device_name = val.substr(val.find("name=") + strlen("name="),  val.size() - strlen("name=") - 2);
		}  else if (val.find("init=") != std::string::npos) {
			auto init = val.substr(val.find("init=") + strlen("init="));
			if (init.size() == 1) {
				device_info.is_init = init[0];
			}
		} else if (val.find("snid=") != std::string::npos) {
			device_info.sn_name = val.substr(val.find("snid=") + strlen("snid="),  val.size() - strlen("snid=") - 2);
			//LOG_PrintWarn("device_info.sn_name = val : %s\n", val.c_str());
		}else if(val.find("busy=") != std::string::npos){
			device_info.busy = val.substr(val.find("busy=") + strlen("busy="),  val.size() - strlen("busy=") - 2);
		}else if(val.find("version=") != std::string::npos){
			device_info.version = val.substr(val.find("version=") + strlen("version="), val.size() - strlen("version=") - 2);
		}else if(val.find("power=") != std::string::npos){
			device_info.power =  val.substr(val.find("power=") + strlen("power="),  val.size() - strlen("power=") - 2);
		}else if(val.find("mac=") != std::string::npos){
			device_info.device_mac = val.substr(val.find("mac=") + strlen("mac="),  val.size() - strlen("mac=") - 2);
		}else if(val.find("passwd=") != std::string::npos){
			device_info.passwd =  val.substr(val.find("passwd=") + strlen("passwd="),  val.size() - strlen("passwd=") - 2);
		}else if(val.find("ssid=") != std::string::npos){
			device_info.ssid = val.substr(val.find("ssid=") + strlen("ssid="),  val.size() - strlen("ssid=") - 2);
		}else if(val.find("ab=") != std::string::npos){
			device_info.ability = val.substr(val.find("ab=") + strlen("ab="),  val.size() - strlen("ab=") - 2);
		}
	}

	return device_info;
}



bool Mdns::browserNetWorkDevice(set<NetworkDeviceAbility> & deviceList){
	vector<string> infos;
	getCmdInfo("/usr/share/avahi/avahi.sh", infos);
	for (int index = 0; index < infos.size(); index++) {
		DeviceInfo info = ParseDeviceMDnsData(infos[index]);
		if(!info.ability.empty()){
			//LOG_PrintWarn("serviceName:%s, name: %s, busy:%s ,ssid:%s , snid:%s, version:%s, mac:%s, ip:%s , ssid:%s, power:%s, init:%s, ability: %s\n",
			//info.service_name.c_str(),
			//info.device_name.c_str(), info.busy.c_str(), info.ssid.c_str(), info.sn_name.c_str(), info.version.c_str(), info.device_mac.c_str(), info.device_ip.c_str(), info.ssid.c_str(), info.power.c_str(), info.is_init.c_str(), info.ability.c_str());
			NetworkDeviceAbility devAblity;
			if(info.sn_name.empty()){
				continue;
			}
			string sn_code = info.sn_name.substr(info.sn_name.length() - 6);
			devAblity.serverName = "v520d_" + sn_code +  "&rtsp://" + info.device_ip + ":554/live/mainstream";
			vector<string> abilities = stringSplit(info.ability, '&');
			devAblity.rtspBility = abilities[0][5] - 48;
			devAblity.ip = info.device_ip;
			deviceList.insert(devAblity);
		}
	}
	return true;
}

#if 0
bool Mdns::browserNetWorkDevice(set<NetworkDeviceAbility> & deviceList){
	std::set<DeviceInfo> deviceSet;
    MdnsService::getDeviceSet(deviceSet);   
    for(auto it = deviceSet.begin(); it != deviceSet.end(); it++){
        DeviceInfo info = *it;
		//LOG_PrintWarn("serviceName:%s, name: %s, busy:%s ,ssid:%s , snid:%s, version:%s, mac:%s, ip:%s , ssid:%s, power:%s, init:%s, ability: %s\n",
		//info.service_name.c_str(),
		//info.device_name.c_str(), info.busy.c_str(), info.ssid.c_str(), info.sn_name.c_str(), info.version.c_str(), info.device_mac.c_str(), info.device_ip.c_str(), info.ssid.c_str(), info.power.c_str(), info.is_init.c_str(), info.ability.c_str());
		if(!info.ability.empty()){
			NetworkDeviceAbility devAblity;
			vector<string> serverNames = stringSplit(info.service_name, '.');
			string serverName = serverNames[0];
			devAblity.serverName = serverName + "&" + "rtsp://" + info.device_ip + ":554/live/mainstream";
			vector<string> abilities = stringSplit(info.ability, '&');
			devAblity.rtspBility = abilities[0][5] - 48;
			deviceList.insert(devAblity);
		}	
    }

#if 0
	set<NetworkDeviceAbility>::iterator it;
	for(it = deviceList.begin(); it != deviceList.end(); it++){
		NetworkDeviceAbility devAblity = *it;
		LOG_PrintWarn("------------------add network device succeed servicename: %s   ability: %d------------------\n", devAblity.serverName.c_str(), devAblity.rtspBility);
	}
#endif
	return true;	
}
#endif
}
